package com.polaris.live.ui.main.live

import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.polaris.live.adapter.live.HomeFollowRecommendAdapter
import com.polaris.live.adapter.live.HomeFollowUserAdapter
import com.polaris.live.common.cacha.CacheUtil
import com.polaris.live.common.ext.setOnSingleClickListener
import com.polaris.live.common.mvvm.base2.BaseVbFragment
import com.polaris.live.common.network.AppException
import com.polaris.live.common.network.parseState
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.constant.LiveConst
import com.polaris.live.constant.UserConst
import com.polaris.live.databinding.FragmentLiveFollowListBinding
import com.polaris.live.manager.UserStateManager
import com.polaris.live.popup.GlobalPopupManager
import com.polaris.live.resp.back_resp.DisplayUserBean
import com.polaris.live.resp.back_resp.copyState
import com.polaris.live.utils.LiveUtils
import com.polaris.live.utils.StartCallProxy
import com.polaris.live.utils.StartLiveProxy
import com.polaris.live.utils.interfaces.OnAutoRefreshListener
import com.polaris.live.utils.state.getDisplayPosition
import com.polaris.live.viewmodel.home.LiveFollowViewModel

/**
 * LiveFollowListFragment
 *
 * @author Created by 半仙 on 2024/3/5/005 9:39
 */
class LiveFollowListFragment : BaseVbFragment<LiveFollowViewModel, FragmentLiveFollowListBinding>(),
    OnAutoRefreshListener {

    private val mAdapter by lazy { HomeFollowUserAdapter() }
    private val mRecommendAdapter by lazy { HomeFollowRecommendAdapter() }

    private var lastRefreshTime: Long? = null
    private var refreshTime = 1000

    override fun initView(savedInstanceState: Bundle?) {
        mBinding.recycler.apply {
            layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
            adapter = mAdapter
            itemAnimator = null
        }
        mBinding.recycler2.apply {
            layoutManager = GridLayoutManager(context, 2, GridLayoutManager.VERTICAL, false)
            adapter = mRecommendAdapter
            itemAnimator = null
        }
        initListener()
        initObserver()
        onRefresh()
    }

    override fun initData() {
        super.initData()
        mViewModel.getLiveData()
    }

    private fun onRefresh() {
        mBinding.refresh.setOnRefreshListener {
            mViewModel.pageNumber = 0
            mViewModel.getLiveData()
        }

        mBinding.refresh.setOnLoadMoreListener {
            mViewModel.pageNumber += 1
            mViewModel.getLiveData()
        }
    }

    private fun initObserver() {
        mViewModel.livesLiveData.observe(this) { resultState ->
            mBinding.widgetLoading.visibility = View.GONE
            parseState(resultState, {
                lastRefreshTime = CacheUtil.getServerTime()
                //如果number = 0 就可以理解为刷新了
                if (mViewModel.pageNumber == 0) {
                    mAdapter.setList(it.list)
                    if (it.list.isNotEmpty()) {
                        mBinding.widgetEmpty.visibility = View.GONE
                    }
                } else {
                    mAdapter.addData(it.list)
                }
            }, {
                showError(it)
            })
            mBinding.refresh.finishRefresh()
            mBinding.refresh.finishLoadMore()
        }
        mViewModel.recommendData.observe(this) { resultState ->
            mBinding.widgetLoading.visibility = View.GONE
            parseState(resultState, {
                if (it.isEmpty()) {
                    mBinding.recommendedTv.visibility = View.GONE
                } else {
                    mBinding.recommendedTv.visibility = View.VISIBLE
                    mBinding.widgetEmpty.visibility = View.GONE
                }
                mRecommendAdapter.setList(it)
            })
        }
        mViewModel.notHaveData.observe(this) {
            mBinding.widgetLoading.visibility = View.GONE
            mBinding.widgetEmpty.visibility = View.VISIBLE
        }

        UserStateManager.observe(this, {
            getDisplayUserIds()
        }, { messages ->
            val indices = mBinding.recycler.getDisplayPosition(mAdapter.data)?.indices
                ?: mAdapter.data.indices

            messages.forEach { message ->
                for (i in indices) {
                    val item = mAdapter.getItem(i)
                    if (item is DisplayUserBean && item.base.userId == message.state.userId) {
                        mAdapter.setData(i, item.copyState(message))
                        break
                    }
                }
            }
        })
    }

    private fun getDisplayUserIds(): List<Long> {
        val wrapper = mAdapter.recyclerView.getDisplayPosition(mAdapter.data)
            ?: return emptyList()

        return mAdapter.data.subList(wrapper.firstPosition, wrapper.lastPosition).mapNotNull {
            if (it is DisplayUserBean) {
                it.base.userId
            } else {
                null
            }
        }
    }

    private fun initListener() {
        mAdapter.setOnItemClickListener { _, _, position ->
            val item = mAdapter.getItemOrNull(position) ?: return@setOnItemClickListener
            GlobalPopupManager.showCompletePopup(requireContext(), isOk = {
                if (item is DisplayUserBean) {
                    if (LiveUtils.isToWaiting(item)) {
                        StartCallProxy.builder(this).startCall(
                            mViewModel,
                            UserConst.From.LIVE,
                            UserConst.LastFrom.LIVE,
                            LiveConst.SenderFrom.MANUAL,
                            item.base.userId, item.base
                        )
                    } else {
                        LiveUtils.invokeSpectator(requireContext(), item)
                    }
                }
            })
        }
        mRecommendAdapter.setOnItemClickListener { _, _, position ->
            val item = mRecommendAdapter.getItemOrNull(position) ?: return@setOnItemClickListener
            GlobalPopupManager.showCompletePopup(requireContext(), isOk = {
                if (LiveUtils.isToWaiting(item)) {
                    StartCallProxy.builder(this).startCall(
                        mViewModel,
                        UserConst.From.LIVE,
                        UserConst.LastFrom.LIVE,
                        LiveConst.SenderFrom.MANUAL,
                        item.base.userId, item.base
                    )
                } else {
                    LiveUtils.invokeSpectator(requireContext(), item)
                }
            })
        }
        mBinding.recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    updateUserStateObserve()
                }
            }
        })
        mBinding.ivStartLive.setOnSingleClickListener {
            StartLiveProxy.builder(this)
                .startLive(mViewModel, LiveConst.Type.ONLY_LIVE)
        }

    }

    private fun updateUserStateObserve(userIds: List<Long> = getDisplayUserIds()) {
        UserStateManager.updateUserObserve(this, userIds)
    }

    private fun showError(appException: AppException) {
        if (mAdapter.data.isNotEmpty()) {
            ToastGravity.showGravity(appException.errorMsg)
        }
        //当number是0  并且没有关注和推荐的时候  展示空布局
        if (mViewModel.pageNumber == 0 && mAdapter.data.isEmpty() && mRecommendAdapter.data.isEmpty()) {
            mBinding.widgetEmpty.visibility = View.VISIBLE
        }
    }

    override fun onResume() {
        toRefresh()

        super.onResume()
    }

    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)

        if (!hidden) {
            toRefresh()
        }
    }

    private fun toRefresh() {
        if (isLoadData()) {
            val lastRefreshTime = lastRefreshTime
            if (lastRefreshTime == null || CacheUtil.getServerTime() - lastRefreshTime > 5 * 60 * refreshTime) {
                onAutoRefresh()
            }
        }
    }

    override fun onAutoRefresh() {
        if (!isCreated() || !isLoadData()) {
            return
        }

        mBinding.recycler.scrollToPosition(0)
        mBinding.refresh.autoRefresh()
    }
}